home *** CD-ROM | disk | FTP | other *** search
- // RTLI program interface
-
- unit LIPrgInt;
-
- interface
-
- uses
- Windows;
-
- type
- PLocInfo = ^TLocInfo;
- TLocInfo = record
- liUnitName: String;
- liUnitBegOfs: Integer;
- liUnitEndOfs: Integer;
- liLineOfs: Integer;
- liLineNo: Integer;
- liFileName: String;
- liPubSym1Ofs: Longint;
- liPubSym2Ofs: Longint;
- liPubSym1Name: String;
- liPubSym2Name: String;
- end;
-
- function GetLocationInfo(CodeAddr: Pointer; var LocInfo: TLocInfo): Boolean;
- function RTLIAvailable: Boolean;
- //procedure ___Fixup___;
-
- implementation
-
- uses LIUtils;
-
- var
- RTLIResPtr: Pointer = nil;
- RTLIResInfo: HRSRC;
- RTLIResource: THandle;
- const
- LinkerOffset = $1000;
-
- {procedure ___Fixup___;
- begin
- end;}
-
- function RTLIAvailable: Boolean;
- begin
- Result := Assigned(RTLIResPtr);
- end;
-
- function GetLocationInfo(CodeAddr: Pointer; var LocInfo: TLocInfo): Boolean;
- var
- P1,P2,P3: PChar;
- CodeOfs: DWORD; // absolute CodeAddr;
- OfsDelta: DWORD;
- Count,Delta1,Delta2,CurOfs,CurLine: integer;
- begin
- FillChar(LocInfo, SizeOf(TLocInfo), 0);
- P1 := RTLIResPtr;
- Result := Assigned(P1);
- if Result then
- with PRTLIHeader(P1)^, LocInfo do
- begin
- // This logic returns the wrong result some times.
- // OfsDelta := Integer(@___Fixup___) - rtliFixup;
- // Better to use HInstance (=$00400000 for EXE files) and the Borland
- // linker offset ($1000)
- OfsDelta := DWORD(HInstance) + LinkerOffset;
- CodeOfs := DWORD(CodeAddr);
- Dec(CodeOfs, OfsDelta);
- Inc(P1, SizeOf(TRTLIHeader));
- // Find the unit
- Count := rtliUnitCount;
- while Count > 0 do
- begin
- P2 := P1 + Ord(P1[4]) + 5;
- if (CodeOfs >= DWORD(PDWord(P1)^)) and (CodeOfs < DWORD(PDWord(P2)^)) then
- begin
- DecodeString(liUnitName, P1 + 4);
- liUnitBegOfs := integer(DWORD(PDWord(P1)^) + OfsDelta);
- liUnitEndOfs := integer(DWORD(PDWord(P2)^) + OfsDelta);
- end;
- Dec(Count);
- P1 := P2;
- end;
- Inc(P1, 4); // Skip the ending offset
- if liUnitName <> '' then
- begin
- // Find the public symbol
- CurOfs := 0;
- P3 := P1;
- Count := rtliPublicCount;
- while Count > 0 do
- begin
- P2 := DecodeSymbolOfs(P1 + Ord(P1^) + 1, Delta1);
- P3 := DecodeSymbolOfs(P2 + Ord(P2^) + 1, Delta2);
- if (CodeOfs >= DWORD(CurOfs + Delta1)) and (CodeOfs < DWORD(CurOfs + Delta1 + Delta2)) then
- begin
- liPubSym1Ofs := Integer(OfsDelta) + CurOfs + Delta1;
- liPubSym2Ofs := liPubSym1Ofs + Delta2;
- DecodeString(liPubSym1Name, P1);
- DecodeString(liPubSym2Name, P2);
- end;
- P1 := P2;
- Inc(CurOfs, Delta1);
- Dec(Count);
- end;
- P1 := P3;
- Count := rtliLineCount;
- CurLine := 0;
- // Find line number information
- while Count > 0 do
- begin
- P1 := DecodeLineNumber(P1, Delta1, Delta2, liFileName);
- if Delta1 = MaxInt then
- begin
- CurLine := 0; // New file
- CurOfs := 0;
- end
- else
- begin
- liLineOfs := CurOfs + Delta2;
- if (liLineOfs + Integer(OfsDelta) >= liUnitBegOfs) and (liLineOfs + Integer(OfsDelta) < liUnitEndOfs) and (CodeOfs < DWORD(liLineOfs)) then
- begin
- if CurLine = 0 then
- begin
- liLineOfs := 0;
- liLineNo := 0;
- end
- else
- begin
- liLineNo := CurLine;
- liLineOfs := CurOfs + Integer(OfsDelta);
- end;
- Exit;
- end;
- Inc(CurLine, Delta1);
- Inc(CurOfs , Delta2);
- Dec(Count);
- end;
- end;
- liFileName := '';
- liLineNo := 0;
- liLineOfs := 0;
- end;
- end;
- end;
-
- initialization
- RTLIResInfo := FindResource(HInstance, PChar($7777), RT_RCDATA);
- if RTLIResInfo <> 0 then
- begin
- RTLIResource := LoadResource(HInstance, RTLIResInfo);
- if RTLIResource <> 0 then
- RTLIResPtr := LockResource(RTLIResource);
- end;
-
- finalization
- UnlockResource(RTLIResource);
- FreeResource(RTLIResInfo);
- end.
-